ComponentOne Basic Library for UWP
Basic Library Overview / TreeView for UWP / TreeView Behavior / Load on Demand
In This Topic
    Load on Demand
    In This Topic

    Instead of fully populating each node when the application starts, you can use a technique called delayed loading, where nodes are populated on demand when the user expands them. This allows the application to load faster and use resources more efficiently

    To implement the delayed loading nodes, use the following code:

    Visual Basic
    Copy Code
    Public Sub New()
          InitializeComponent()
          ' No changes here.
          ' ...
          ' Initialize the C1TreeView
          InitializeTreeView()
    End Sub
    Private Sub InitializeTreeView()
          ' Remove items that were added at design time
          _tv.Items.Clear()
    
          ' Scan every type in the assembly
          For Each t As Type In _tv.[GetType]().Assembly.GetTypes()
                If t.IsPublic AndAlso Not t.IsSpecialName AndAlso Not t.IsAbstract Then
                      ' Add node for this type
                      Dim node As New C1TreeViewItem()
                      node.Header = t.Name
                      node.FontWeight = FontWeights.Bold
                      _tv.Items.Add(node)
                      ' Add subnodes for properties, events, and methods
                      node.Items.Add(CreateMemberNode("Properties", t, MemberTypes.[Property]))
                      node.Items.Add(CreateMemberNode("Events", t, MemberTypes.[Event]))
                      node.Items.Add(CreateMemberNode("Methods", t, MemberTypes.Method))
                End If
          Next
    End Sub
    Private Function CreateMemberNode(header As String, memberTypes As MemberTypes) As C1TreeViewItem
          ' Create the node
          Dim node As New C1TreeViewItem()
          node.Header = header
          node.Foreground = New SolidColorBrush(Colors.DarkGray)
          ' Hook up event hander to populate the node before expanding it
          AddHandler node.Expanding, AddressOf node_Expanding
          ' Save information needed to populate the node
          node.Tag = memberTypes
          ' Add a dummy node so this node can be expanded
          node.Items.Add(New C1TreeViewItem())
          node.IsExpanded = False
          ' Finish
          Return node
    End Function
    'populate the node
    Private Sub node_Expanding(sender As Object, e As RoutedEventArgs)
          ' Get the node that fired the event
          Dim node As C1TreeViewItem = TryCast(sender, C1TreeViewItem)
          ' Unhook event handler (we'll populate the node and be done with it)
          RemoveHandler node.Expanding, AddressOf node_Expanding
          ' Remove dummy node
          node.Items.Clear()
          ' Populate the node
          Dim type As Type = DirectCast(node.Parent.Tag, Type)
          Dim memberTypes As MemberTypes = DirectCast(node.Tag, MemberTypes)
          Dim bf As BindingFlags = BindingFlags.[Public] Or BindingFlags.Instance
          For Each mi As MemberInfo In type.GetMembers(bf)
                If mi.MemberType = memberTypes Then
                      If Not mi.Name.StartsWith("get_") AndAlso Not mi.Name.StartsWith("set_") Then
                            Dim item As New C1TreeViewItem()
                            item.Header = mi.Name
                            item.FontSize = 12
                            node.Items.Add(item)
                      End If
                End If
          Next
    End Sub
    

    C#
    Copy Code
    public Page()
    {
        InitializeComponent();
        // No changes here.
        // ...
        // Initialize the C1TreeView
        InitializeTreeView();          
    }
    void InitializeTreeView()
    {
      // Remove items that were added at design time
      _tv.Items.Clear();
    
       // Scan every type in the assembly
      foreach (Type t in _tv.GetType().Assembly.GetTypes())
      {
        if (t.IsPublic && !t.IsSpecialName && !t.IsAbstract)
        {
          // Add node for this type
          C1TreeViewItem node = new C1TreeViewItem();
          node.Header = t.Name;
          node.FontWeight = FontWeights.Bold;
          _tv.Items.Add(node);
          // Add subnodes for properties, events, and methods
          node.Items.Add(CreateMemberNode("Properties", t, MemberTypes.Property));
          node.Items.Add(CreateMemberNode("Events", t, MemberTypes.Event));
          node.Items.Add(CreateMemberNode("Methods", t, MemberTypes.Method));
        }
      }
    }
    C1TreeViewItem CreateMemberNode(string header, MemberTypes memberTypes)
    {
      // Create the node
      C1TreeViewItem node = new C1TreeViewItem();
      node.Header = header;
      node.Foreground = new SolidColorBrush(Colors.DarkGray);
       // Hook up event hander to populate the node before expanding it
      node.Expanding += node_Expanding;
       // Save information needed to populate the node
      node.Tag = memberTypes;
       // Add a dummy node so this node can be expanded
      node.Items.Add(new C1TreeViewItem());
      node.IsExpanded = false;
       // Finish
      return node;         
    }
    //populate the node
    void node_Expanding(object sender, RoutedEventArgs e)
    {
      // Get the node that fired the event
      C1TreeViewItem node = sender as C1TreeViewItem;
      // Unhook event handler (we'll populate the node and be done with it)
      node.Expanding -= node_Expanding;
       // Remove dummy node
      node.Items.Clear();
       // Populate the node
      Type type = (Type)node.Parent.Tag;
      MemberTypes memberTypes = (MemberTypes)node.Tag;
       BindingFlags bf = BindingFlags.Public | BindingFlags.Instance;
      foreach (MemberInfo mi in type.GetMembers(bf))
      {
        if (mi.MemberType == memberTypes)
        {
          if (!mi.Name.StartsWith("get_") && !mi.Name.StartsWith("set_"))
          {
            C1TreeViewItem item = new C1TreeViewItem();
            item.Header = mi.Name;
            item.FontSize = 12;
            node.Items.Add(item);
          }
        }
      }      
    }
    

    This implementation hooks up an event hander for the Expanding event, so we can populate the node when the user tries to expand it. We also save the information we will need to populate the node in the Tag property. Finally, we add a dummy child node so the user will be able to expand this node and trigger the Expanding event that will populate the node.

    Note that instead of using the Tag property, we could also have derived a custom class from C1TreeViewItem and built all the delay-load logic into that class. This would be a more elegant approach, but unfortunately UWP doesn't support template inheritance. If you derive a class from a class that has a template (such as Button or C1TreeViewItem), the template is not inherited, and you have to provide a template yourself or your derived class will be just an empty control.

    See Also